rename to gtk_text_mark_get_visible
authorHavoc Pennington <hp@redhat.com>
Tue, 7 Nov 2000 21:01:02 +0000 (21:01 +0000)
committerHavoc Pennington <hp@src.gnome.org>
Tue, 7 Nov 2000 21:01:02 +0000 (21:01 +0000)
2000-11-07  Havoc Pennington  <hp@redhat.com>

* gtk/gtktextmark.c (gtk_text_mark_is_visible): rename
to gtk_text_mark_get_visible

* gtk/gtktextlayout.c (gtk_text_layout_move_iter_to_line_end): fix
bug that was generating an invalid iterator

* gtk/gtktextiter.c (gtk_text_iter_get_offset): move call to
ensure_char_offsets() in front of code placing the iter in an
invalid state.

* gtk/gtktextbuffer.c (gtk_text_buffer_paste_primary):
make override_location arg const
(paste): Replace the selection if we paste into the
current selection

* gtk/gtkselection.h: Remove "GtkSelectioData"
(struct _GtkSelectionData): move the definition here.

* gtk/gtktextbuffer.c (gtk_text_buffer_update_primary_selection):
Export the GTK_TEXT_BUFFER_CONTENTS target for in-process copies

* gtk/gtktextiter.c (gtk_text_iter_get_tags): New function

* gtk/gtktextbuffer.c (gtk_text_buffer_insert_range): implement
(gtk_text_buffer_insert_range_interactive): implement
(gtk_text_buffer_get_tags): Remove, replaced by
gtk_text_iter_get_tags()

* gtk/gtktextiter.c (gtk_text_iter_forward_search): Add a search
limit parameter, to avoid infinite linear scan.
(gtk_text_iter_backward_search): Add search limit
(gtk_text_iter_forward_find_char): Add search limit
(gtk_text_iter_backward_find_char): Add search limit

22 files changed:
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
gtk/gtkselection.c
gtk/gtkselection.h
gtk/gtktextbtree.c
gtk/gtktextbuffer.c
gtk/gtktextbuffer.h
gtk/gtktextiter.c
gtk/gtktextiter.h
gtk/gtktextlayout.c
gtk/gtktextmark.c
gtk/gtktextmark.h
gtk/gtktextsegment.c
gtk/gtktextview.c
gtk/gtkwidget.h
gtk/testtext.c
tests/testtext.c

index 66126a253a1fa32bce1f3a7b8a8c556923b36881..9547e7dae9bfd1d05dea360dec60c6bfb46555e5 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,39 @@
+2000-11-07  Havoc Pennington  <hp@redhat.com>
+
+       * gtk/gtktextmark.c (gtk_text_mark_is_visible): rename 
+       to gtk_text_mark_get_visible
+
+       * gtk/gtktextlayout.c (gtk_text_layout_move_iter_to_line_end): fix
+       bug that was generating an invalid iterator
+
+       * gtk/gtktextiter.c (gtk_text_iter_get_offset): move call to
+       ensure_char_offsets() in front of code placing the iter in an
+       invalid state.
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_paste_primary):
+       make override_location arg const
+       (paste): Replace the selection if we paste into the 
+       current selection
+
+       * gtk/gtkselection.h: Remove "GtkSelectioData"
+       (struct _GtkSelectionData): move the definition here.
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_update_primary_selection):
+       Export the GTK_TEXT_BUFFER_CONTENTS target for in-process copies
+
+       * gtk/gtktextiter.c (gtk_text_iter_get_tags): New function
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_insert_range): implement
+       (gtk_text_buffer_insert_range_interactive): implement
+       (gtk_text_buffer_get_tags): Remove, replaced by
+       gtk_text_iter_get_tags()
+
+       * gtk/gtktextiter.c (gtk_text_iter_forward_search): Add a search
+       limit parameter, to avoid infinite linear scan.
+       (gtk_text_iter_backward_search): Add search limit
+       (gtk_text_iter_forward_find_char): Add search limit
+       (gtk_text_iter_backward_find_char): Add search limit
+
 2000-11-07  Alexander Larsson  <alla@lysator.liu.se>
 
        * gdk/linux-fb/gdkcolor-fb.c, gdk/linux-fb/gdkdnd-fb.c,
index 66126a253a1fa32bce1f3a7b8a8c556923b36881..9547e7dae9bfd1d05dea360dec60c6bfb46555e5 100644 (file)
@@ -1,3 +1,39 @@
+2000-11-07  Havoc Pennington  <hp@redhat.com>
+
+       * gtk/gtktextmark.c (gtk_text_mark_is_visible): rename 
+       to gtk_text_mark_get_visible
+
+       * gtk/gtktextlayout.c (gtk_text_layout_move_iter_to_line_end): fix
+       bug that was generating an invalid iterator
+
+       * gtk/gtktextiter.c (gtk_text_iter_get_offset): move call to
+       ensure_char_offsets() in front of code placing the iter in an
+       invalid state.
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_paste_primary):
+       make override_location arg const
+       (paste): Replace the selection if we paste into the 
+       current selection
+
+       * gtk/gtkselection.h: Remove "GtkSelectioData"
+       (struct _GtkSelectionData): move the definition here.
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_update_primary_selection):
+       Export the GTK_TEXT_BUFFER_CONTENTS target for in-process copies
+
+       * gtk/gtktextiter.c (gtk_text_iter_get_tags): New function
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_insert_range): implement
+       (gtk_text_buffer_insert_range_interactive): implement
+       (gtk_text_buffer_get_tags): Remove, replaced by
+       gtk_text_iter_get_tags()
+
+       * gtk/gtktextiter.c (gtk_text_iter_forward_search): Add a search
+       limit parameter, to avoid infinite linear scan.
+       (gtk_text_iter_backward_search): Add search limit
+       (gtk_text_iter_forward_find_char): Add search limit
+       (gtk_text_iter_backward_find_char): Add search limit
+
 2000-11-07  Alexander Larsson  <alla@lysator.liu.se>
 
        * gdk/linux-fb/gdkcolor-fb.c, gdk/linux-fb/gdkdnd-fb.c,
index 66126a253a1fa32bce1f3a7b8a8c556923b36881..9547e7dae9bfd1d05dea360dec60c6bfb46555e5 100644 (file)
@@ -1,3 +1,39 @@
+2000-11-07  Havoc Pennington  <hp@redhat.com>
+
+       * gtk/gtktextmark.c (gtk_text_mark_is_visible): rename 
+       to gtk_text_mark_get_visible
+
+       * gtk/gtktextlayout.c (gtk_text_layout_move_iter_to_line_end): fix
+       bug that was generating an invalid iterator
+
+       * gtk/gtktextiter.c (gtk_text_iter_get_offset): move call to
+       ensure_char_offsets() in front of code placing the iter in an
+       invalid state.
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_paste_primary):
+       make override_location arg const
+       (paste): Replace the selection if we paste into the 
+       current selection
+
+       * gtk/gtkselection.h: Remove "GtkSelectioData"
+       (struct _GtkSelectionData): move the definition here.
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_update_primary_selection):
+       Export the GTK_TEXT_BUFFER_CONTENTS target for in-process copies
+
+       * gtk/gtktextiter.c (gtk_text_iter_get_tags): New function
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_insert_range): implement
+       (gtk_text_buffer_insert_range_interactive): implement
+       (gtk_text_buffer_get_tags): Remove, replaced by
+       gtk_text_iter_get_tags()
+
+       * gtk/gtktextiter.c (gtk_text_iter_forward_search): Add a search
+       limit parameter, to avoid infinite linear scan.
+       (gtk_text_iter_backward_search): Add search limit
+       (gtk_text_iter_forward_find_char): Add search limit
+       (gtk_text_iter_backward_find_char): Add search limit
+
 2000-11-07  Alexander Larsson  <alla@lysator.liu.se>
 
        * gdk/linux-fb/gdkcolor-fb.c, gdk/linux-fb/gdkdnd-fb.c,
index 66126a253a1fa32bce1f3a7b8a8c556923b36881..9547e7dae9bfd1d05dea360dec60c6bfb46555e5 100644 (file)
@@ -1,3 +1,39 @@
+2000-11-07  Havoc Pennington  <hp@redhat.com>
+
+       * gtk/gtktextmark.c (gtk_text_mark_is_visible): rename 
+       to gtk_text_mark_get_visible
+
+       * gtk/gtktextlayout.c (gtk_text_layout_move_iter_to_line_end): fix
+       bug that was generating an invalid iterator
+
+       * gtk/gtktextiter.c (gtk_text_iter_get_offset): move call to
+       ensure_char_offsets() in front of code placing the iter in an
+       invalid state.
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_paste_primary):
+       make override_location arg const
+       (paste): Replace the selection if we paste into the 
+       current selection
+
+       * gtk/gtkselection.h: Remove "GtkSelectioData"
+       (struct _GtkSelectionData): move the definition here.
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_update_primary_selection):
+       Export the GTK_TEXT_BUFFER_CONTENTS target for in-process copies
+
+       * gtk/gtktextiter.c (gtk_text_iter_get_tags): New function
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_insert_range): implement
+       (gtk_text_buffer_insert_range_interactive): implement
+       (gtk_text_buffer_get_tags): Remove, replaced by
+       gtk_text_iter_get_tags()
+
+       * gtk/gtktextiter.c (gtk_text_iter_forward_search): Add a search
+       limit parameter, to avoid infinite linear scan.
+       (gtk_text_iter_backward_search): Add search limit
+       (gtk_text_iter_forward_find_char): Add search limit
+       (gtk_text_iter_backward_find_char): Add search limit
+
 2000-11-07  Alexander Larsson  <alla@lysator.liu.se>
 
        * gdk/linux-fb/gdkcolor-fb.c, gdk/linux-fb/gdkdnd-fb.c,
index 66126a253a1fa32bce1f3a7b8a8c556923b36881..9547e7dae9bfd1d05dea360dec60c6bfb46555e5 100644 (file)
@@ -1,3 +1,39 @@
+2000-11-07  Havoc Pennington  <hp@redhat.com>
+
+       * gtk/gtktextmark.c (gtk_text_mark_is_visible): rename 
+       to gtk_text_mark_get_visible
+
+       * gtk/gtktextlayout.c (gtk_text_layout_move_iter_to_line_end): fix
+       bug that was generating an invalid iterator
+
+       * gtk/gtktextiter.c (gtk_text_iter_get_offset): move call to
+       ensure_char_offsets() in front of code placing the iter in an
+       invalid state.
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_paste_primary):
+       make override_location arg const
+       (paste): Replace the selection if we paste into the 
+       current selection
+
+       * gtk/gtkselection.h: Remove "GtkSelectioData"
+       (struct _GtkSelectionData): move the definition here.
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_update_primary_selection):
+       Export the GTK_TEXT_BUFFER_CONTENTS target for in-process copies
+
+       * gtk/gtktextiter.c (gtk_text_iter_get_tags): New function
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_insert_range): implement
+       (gtk_text_buffer_insert_range_interactive): implement
+       (gtk_text_buffer_get_tags): Remove, replaced by
+       gtk_text_iter_get_tags()
+
+       * gtk/gtktextiter.c (gtk_text_iter_forward_search): Add a search
+       limit parameter, to avoid infinite linear scan.
+       (gtk_text_iter_backward_search): Add search limit
+       (gtk_text_iter_forward_find_char): Add search limit
+       (gtk_text_iter_backward_find_char): Add search limit
+
 2000-11-07  Alexander Larsson  <alla@lysator.liu.se>
 
        * gdk/linux-fb/gdkcolor-fb.c, gdk/linux-fb/gdkdnd-fb.c,
index 66126a253a1fa32bce1f3a7b8a8c556923b36881..9547e7dae9bfd1d05dea360dec60c6bfb46555e5 100644 (file)
@@ -1,3 +1,39 @@
+2000-11-07  Havoc Pennington  <hp@redhat.com>
+
+       * gtk/gtktextmark.c (gtk_text_mark_is_visible): rename 
+       to gtk_text_mark_get_visible
+
+       * gtk/gtktextlayout.c (gtk_text_layout_move_iter_to_line_end): fix
+       bug that was generating an invalid iterator
+
+       * gtk/gtktextiter.c (gtk_text_iter_get_offset): move call to
+       ensure_char_offsets() in front of code placing the iter in an
+       invalid state.
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_paste_primary):
+       make override_location arg const
+       (paste): Replace the selection if we paste into the 
+       current selection
+
+       * gtk/gtkselection.h: Remove "GtkSelectioData"
+       (struct _GtkSelectionData): move the definition here.
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_update_primary_selection):
+       Export the GTK_TEXT_BUFFER_CONTENTS target for in-process copies
+
+       * gtk/gtktextiter.c (gtk_text_iter_get_tags): New function
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_insert_range): implement
+       (gtk_text_buffer_insert_range_interactive): implement
+       (gtk_text_buffer_get_tags): Remove, replaced by
+       gtk_text_iter_get_tags()
+
+       * gtk/gtktextiter.c (gtk_text_iter_forward_search): Add a search
+       limit parameter, to avoid infinite linear scan.
+       (gtk_text_iter_backward_search): Add search limit
+       (gtk_text_iter_forward_find_char): Add search limit
+       (gtk_text_iter_backward_find_char): Add search limit
+
 2000-11-07  Alexander Larsson  <alla@lysator.liu.se>
 
        * gdk/linux-fb/gdkcolor-fb.c, gdk/linux-fb/gdkdnd-fb.c,
index 66126a253a1fa32bce1f3a7b8a8c556923b36881..9547e7dae9bfd1d05dea360dec60c6bfb46555e5 100644 (file)
@@ -1,3 +1,39 @@
+2000-11-07  Havoc Pennington  <hp@redhat.com>
+
+       * gtk/gtktextmark.c (gtk_text_mark_is_visible): rename 
+       to gtk_text_mark_get_visible
+
+       * gtk/gtktextlayout.c (gtk_text_layout_move_iter_to_line_end): fix
+       bug that was generating an invalid iterator
+
+       * gtk/gtktextiter.c (gtk_text_iter_get_offset): move call to
+       ensure_char_offsets() in front of code placing the iter in an
+       invalid state.
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_paste_primary):
+       make override_location arg const
+       (paste): Replace the selection if we paste into the 
+       current selection
+
+       * gtk/gtkselection.h: Remove "GtkSelectioData"
+       (struct _GtkSelectionData): move the definition here.
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_update_primary_selection):
+       Export the GTK_TEXT_BUFFER_CONTENTS target for in-process copies
+
+       * gtk/gtktextiter.c (gtk_text_iter_get_tags): New function
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_insert_range): implement
+       (gtk_text_buffer_insert_range_interactive): implement
+       (gtk_text_buffer_get_tags): Remove, replaced by
+       gtk_text_iter_get_tags()
+
+       * gtk/gtktextiter.c (gtk_text_iter_forward_search): Add a search
+       limit parameter, to avoid infinite linear scan.
+       (gtk_text_iter_backward_search): Add search limit
+       (gtk_text_iter_forward_find_char): Add search limit
+       (gtk_text_iter_backward_find_char): Add search limit
+
 2000-11-07  Alexander Larsson  <alla@lysator.liu.se>
 
        * gdk/linux-fb/gdkcolor-fb.c, gdk/linux-fb/gdkdnd-fb.c,
index e09da3d65e604f4958837156e5d359c2878c77c5..fdfb1aa157b5ab8c4358221ed8d5c3944ff452f8 100644 (file)
@@ -1720,7 +1720,7 @@ gtk_selection_default_handler (GtkWidget  *widget,
 }
 
 
-GtkSelectioData*
+GtkSelectionData*
 gtk_selection_data_copy (GtkSelectionData *selection_data)
 {
   GtkSelectionData *new_data;
index 668fec4b3a3893711b3991d1633c3ee0543e7d90..4c109d5531863153c4d613ecbbf698b3b9c8bf1b 100644 (file)
 extern "C" {
 #endif /* __cplusplus */
 
-typedef struct _GtkSelectionData GtkSelectioData;
 typedef struct _GtkTargetList    GtkTargetList;
 typedef struct _GtkTargetEntry   GtkTargetEntry;
 
+/* The contents of a selection are returned in a GtkSelectionData
+ * structure. selection/target identify the request.  type specifies
+ * the type of the return; if length < 0, and the data should be
+ * ignored. This structure has object semantics - no fields should be
+ * modified directly, they should not be created directly, and
+ * pointers to them should not be stored beyond the duration of a
+ * callback. (If the last is changed, we'll need to add reference
+ * counting.) The time field gives the timestamp at which the data was
+ * sent.
+ */
+
+struct _GtkSelectionData
+{
+  GdkAtom selection;
+  GdkAtom target;
+  GdkAtom type;
+  gint   format;
+  guchar *data;  
+  gint   length;
+};
+
 struct _GtkTargetEntry {
   gchar *target;
   guint  flags;
@@ -125,8 +145,8 @@ gint gtk_selection_notify          (GtkWidget         *widget,
                                    GdkEventSelection *event);
 gint gtk_selection_property_notify (GtkWidget         *widget,
                                    GdkEventProperty  *event);
-GtkSelectioData *gtk_selection_data_copy (GtkSelectionData *data);
-void            gtk_selection_data_free (GtkSelectionData *data);
+GtkSelectionData *gtk_selection_data_copy (GtkSelectionData *data);
+void             gtk_selection_data_free (GtkSelectionData *data);
 
 
 
index b73ba456c6124f963f4dfd2a45f49c9d849e0d1b..8654c292350ef9a3454ba9730c3acf74953d5e18 100644 (file)
@@ -2435,13 +2435,13 @@ ensure_not_off_end (GtkTextBTree *tree,
 }
 
 static GtkTextLineSegment*
-real_set_mark (GtkTextBTree *tree,
-               GtkTextMark *existing_mark,
-               const gchar *name,
-               gboolean left_gravity,
+real_set_mark (GtkTextBTree      *tree,
+               GtkTextMark       *existing_mark,
+               const gchar       *name,
+               gboolean           left_gravity,
                const GtkTextIter *where,
-               gboolean should_exist,
-               gboolean redraw_selections)
+               gboolean           should_exist,
+               gboolean           redraw_selections)
 {
   GtkTextLineSegment *mark;
   GtkTextIter iter;
@@ -2465,10 +2465,14 @@ real_set_mark (GtkTextBTree *tree,
     }
 
   /* OK if !should_exist and it does already exist, in that case
-     we just move it. */
-
+   * we just move it.
+   */
+  
   iter = *where;
 
+  if (gtk_debug_flags & GTK_DEBUG_TEXT)
+    gtk_text_iter_check (&iter);
+  
   if (mark != NULL)
     {
       if (redraw_selections &&
@@ -2519,6 +2523,9 @@ real_set_mark (GtkTextBTree *tree,
                              mark);
     }
 
+  if (gtk_debug_flags & GTK_DEBUG_TEXT)
+    gtk_text_iter_check (&iter);
+  
   /* Link mark into new location */
   gtk_text_btree_link_segment (mark, &iter);
 
@@ -2531,6 +2538,12 @@ real_set_mark (GtkTextBTree *tree,
 
   redisplay_mark_if_visible (mark);
 
+  if (gtk_debug_flags & GTK_DEBUG_TEXT)
+    gtk_text_iter_check (&iter);
+
+  if (gtk_debug_flags & GTK_DEBUG_TEXT)
+    gtk_text_btree_check (tree);
+  
   return mark;
 }
 
@@ -3716,7 +3729,8 @@ gtk_text_line_byte_to_char_offsets (GtkTextLine *line,
   g_assert (seg->char_count > 0); /* indexable. */
 
   /* offset is now the number of bytes into the current segment we
-     want to go. Count chars into the current segment. */
+   * want to go. Count chars into the current segment.
+   */
 
   if (seg->type == &gtk_text_char_type)
     {
index c3fcf25e171cdf36e4cba20b23a3250aa9fb5578..b48629e6675cdd1b271fcce0be746cbbe52ade6d 100644 (file)
@@ -43,6 +43,7 @@ struct _ClipboardRequest
   gboolean interactive;
   gboolean default_editable;
   gboolean is_clipboard;
+  gboolean replace_selection;
 };
 
 enum {
@@ -66,7 +67,8 @@ enum {
   TARGET_STRING,
   TARGET_TEXT,
   TARGET_COMPOUND_TEXT,
-  TARGET_UTF8_STRING
+  TARGET_UTF8_STRING,
+  TARGET_TEXT_BUFFER_CONTENTS
 };
 
 static void gtk_text_buffer_init       (GtkTextBuffer      *tkxt_buffer);
@@ -494,6 +496,10 @@ gtk_text_buffer_insert_at_cursor (GtkTextBuffer *buffer,
  * want to prevent insertions at ineditable locations if the insertion
  * results from a user action (is interactive).
  *
+ * @default_editable indicates the editability of text that doesn't
+ * have a tag affecting editability applied to it. Typically the
+ * result of gtk_text_view_get_editable() is appropriate here.
+ *
  * Return value: whether text was actually inserted
  **/
 gboolean
@@ -525,6 +531,10 @@ gtk_text_buffer_insert_interactive (GtkTextBuffer *buffer,
  * Calls gtk_text_buffer_insert_interactive () at the cursor
  * position.
  *
+ * @default_editable indicates the editability of text that doesn't
+ * have a tag affecting editability applied to it. Typically the
+ * result of gtk_text_view_get_editable() is appropriate here.
+ * 
  * Return value: whether text was actually inserted
  **/
 gboolean
@@ -546,6 +556,301 @@ gtk_text_buffer_insert_interactive_at_cursor (GtkTextBuffer *buffer,
                                              default_editable);
 }
 
+static gboolean
+possibly_not_text (gunichar ch,
+                   gpointer user_data)
+{
+  return ch == 0xFFFD;
+}
+
+static void
+insert_text_range (GtkTextBuffer     *buffer,
+                   GtkTextIter       *iter,
+                   const GtkTextIter *orig_start,
+                   const GtkTextIter *orig_end,
+                   gboolean           interactive)
+{
+  gchar *text;
+
+  text = gtk_text_iter_get_text (orig_start, orig_end);
+
+  gtk_text_buffer_emit_insert (buffer, iter, text, -1, interactive);
+
+  g_free (text);
+}
+
+typedef struct _Range Range;
+struct _Range
+{
+  GtkTextBuffer *buffer;
+  GtkTextMark *start_mark;
+  GtkTextMark *end_mark;
+  GtkTextMark *whole_end_mark;
+  GtkTextIter *range_start;
+  GtkTextIter *range_end;
+  GtkTextIter *whole_end;
+};
+
+static Range*
+save_range (GtkTextIter *range_start,
+            GtkTextIter *range_end,
+            GtkTextIter *whole_end)
+{
+  Range *r;
+
+  r = g_new (Range, 1);
+
+  r->buffer = gtk_text_iter_get_buffer (range_start);
+  g_object_ref (G_OBJECT (r->buffer));
+  
+  r->start_mark = 
+    gtk_text_buffer_create_mark (gtk_text_iter_get_buffer (range_start),
+                                 NULL,
+                                 range_start,
+                                 TRUE);
+  r->end_mark = 
+    gtk_text_buffer_create_mark (gtk_text_iter_get_buffer (range_start),
+                                 NULL,
+                                 range_end,
+                                 FALSE);
+
+  r->whole_end_mark = 
+    gtk_text_buffer_create_mark (gtk_text_iter_get_buffer (range_start),
+                                 NULL,
+                                 whole_end,
+                                 FALSE);
+
+  r->range_start = range_start;
+  r->range_end = range_end;
+  r->whole_end = whole_end;
+
+  return r;
+}
+
+static void
+restore_range (Range *r)
+{
+  gtk_text_buffer_get_iter_at_mark (r->buffer,
+                                    r->range_start,
+                                    r->start_mark);
+      
+  gtk_text_buffer_get_iter_at_mark (r->buffer,
+                                    r->range_end,
+                                    r->end_mark);
+      
+  gtk_text_buffer_get_iter_at_mark (r->buffer,
+                                    r->whole_end,
+                                    r->whole_end_mark);
+      
+  gtk_text_buffer_delete_mark (r->buffer, r->start_mark);
+  gtk_text_buffer_delete_mark (r->buffer, r->end_mark);
+  gtk_text_buffer_delete_mark (r->buffer, r->whole_end_mark);
+
+  g_object_unref (G_OBJECT (r->buffer));
+  g_free (r); 
+}
+
+static void
+insert_range_untagged (GtkTextBuffer     *buffer,
+                       GtkTextIter       *iter,
+                       const GtkTextIter *orig_start,
+                       const GtkTextIter *orig_end,
+                       gboolean           interactive)
+{
+  GtkTextIter range_start;
+  GtkTextIter range_end;
+  GtkTextIter start, end;
+  GtkTextBuffer *src_buffer;
+  Range *r;
+  
+  if (gtk_text_iter_equal (orig_start, orig_end))
+    return;
+
+  start = *orig_start;
+  end = *orig_end;
+  
+  src_buffer = gtk_text_iter_get_buffer (&start);
+  
+  range_start = start;
+  range_end = start;
+  
+  while (TRUE)
+    {
+      if (gtk_text_iter_equal (&range_start, &range_end))
+        {
+          /* Figure out how to move forward */
+
+          g_assert (gtk_text_iter_compare (&range_end, &end) <= 0);
+          
+          if (gtk_text_iter_equal (&range_end, &end))
+            {
+              /* nothing left to do */
+              break;
+            }
+          else if (gtk_text_iter_get_char (&range_end) == 0xFFFD)
+            {
+              GdkPixbuf *pixbuf = NULL;
+              GtkTextChildAnchor *anchor = NULL;
+              pixbuf = gtk_text_iter_get_pixbuf (&range_end);
+              anchor = gtk_text_iter_get_child_anchor (&range_end);
+
+              if (pixbuf)
+                {
+                  r = save_range (&range_start,
+                                  &range_end,
+                                  &end);
+
+                  gtk_text_buffer_insert_pixbuf (buffer,
+                                                 iter,
+                                                 pixbuf);
+
+                  restore_range (r);
+                  r = NULL;
+                  
+                  gtk_text_iter_next_char (&range_end);
+                  
+                  range_start = range_end;
+                }
+              else if (anchor)
+                {
+                  /* Just skip anchors */
+
+                  gtk_text_iter_next_char (&range_end);
+                  range_start = range_end;
+                }
+              else
+                {
+                  /* The 0xFFFD was in a text segment, so
+                   * keep going. 
+                   */
+                  gtk_text_iter_forward_find_char (&range_end,
+                                                   possibly_not_text, NULL,
+                                                   &end);
+                  
+                  g_assert (gtk_text_iter_compare (&range_end, &end) <= 0);
+                }
+            }
+          else
+            {
+              /* Text segment starts here, so forward search to
+               * find its possible endpoint
+               */
+              gtk_text_iter_forward_find_char (&range_end,
+                                               possibly_not_text, NULL,
+                                               &end);
+              
+              g_assert (gtk_text_iter_compare (&range_end, &end) <= 0);
+            }
+        }
+      else
+        {
+          r = save_range (&range_start,
+                          &range_end,
+                          &end);
+          
+          insert_text_range (buffer,
+                             iter,
+                             &range_start,
+                             &range_end,
+                             interactive);
+
+          restore_range (r);
+          r = NULL;
+          
+          range_start = range_end;
+        }
+    }
+}
+
+static void
+gtk_text_buffer_real_insert_range (GtkTextBuffer     *buffer,
+                                   GtkTextIter       *iter,
+                                   const GtkTextIter *orig_start,
+                                   const GtkTextIter *orig_end,
+                                   gboolean           interactive)
+{
+  /* Find each range of uniformly-tagged text, insert it,
+   * then apply the tags.
+   */
+  GtkTextIter start = *orig_start;
+  GtkTextIter end = *orig_end;
+  GtkTextIter range_start;
+  GtkTextIter range_end;
+  GtkTextBuffer *src_buffer;
+  Range *r;
+  
+  if (gtk_text_iter_equal (orig_start, orig_end))
+    return;
+
+  src_buffer = gtk_text_iter_get_buffer (orig_start);
+  
+  gtk_text_iter_reorder (&start, &end);
+
+  range_start = start;
+  range_end = start;
+
+  while (TRUE)
+    {
+      gint start_offset;
+      GtkTextIter start_iter;
+      GSList *tags;
+      GSList *tmp_list;
+
+      gtk_text_iter_spew (&range_start, "range_start");
+      gtk_text_iter_spew (&range_end, "range_end");
+      gtk_text_iter_spew (&end, "end");
+      
+      if (gtk_text_iter_equal (&range_start, &end))
+        break; /* All done */
+
+      g_assert (gtk_text_iter_compare (&range_start, &end) < 0);
+      
+      gtk_text_iter_forward_to_tag_toggle (&range_end, NULL);
+
+      g_assert (!gtk_text_iter_equal (&range_start, &range_end));
+
+      /* Clamp to the end iterator */
+      if (gtk_text_iter_compare (&range_end, &end) > 0)
+        range_end = end;
+      
+      /* We have a range with unique tags; insert it, and
+       * apply all tags.
+       */
+      start_offset = gtk_text_iter_get_offset (iter);
+
+      r = save_range (&range_start, &range_end, &end);
+
+      printf ("Source range is %d to %d\n",
+              gtk_text_iter_get_offset (&range_start),
+              gtk_text_iter_get_offset (&range_end));
+      
+      insert_range_untagged (buffer, iter, &range_start, &range_end, interactive);
+
+      restore_range (r);
+      r = NULL;
+      
+      gtk_text_buffer_get_iter_at_offset (buffer, &start_iter, start_offset);
+
+      printf ("Dest range is %d to %d\n",
+              gtk_text_iter_get_offset (&start_iter),
+              gtk_text_iter_get_offset (iter));
+      
+      tags = gtk_text_iter_get_tags (&range_start);
+      tmp_list = tags;
+      while (tmp_list != NULL)
+        {
+          gtk_text_buffer_apply_tag (buffer,
+                                     tmp_list->data,
+                                     &start_iter,
+                                     iter);
+          
+          tmp_list = g_slist_next (tmp_list);
+        }
+      g_slist_free (tags);
+
+      range_start = range_end;
+    }
+}
 
 /**
  * gtk_text_buffer_insert_range:
@@ -576,11 +881,27 @@ gtk_text_buffer_insert_range (GtkTextBuffer     *buffer,
   g_return_if_fail (gtk_text_iter_get_buffer (start) !=
                     gtk_text_iter_get_buffer (end));
   g_return_if_fail (gtk_text_iter_get_buffer (start)->tag_table !=
-                    buffer->tag_table);
+                    buffer->tag_table);  
 
-  /* FIXME */
+  gtk_text_buffer_real_insert_range (buffer, iter, start, end, FALSE);
 }
 
+/**
+ * gtk_text_buffer_insert_range_interactive:
+ * @buffer: a #GtkTextBuffer
+ * @iter: a position in @buffer
+ * @start: a position in a #GtkTextBuffer
+ * @end: another position in the same buffer as @start
+ * @default_editable: default editability of the buffer
+ *
+ * Same as gtk_text_buffer_insert_range(), but does nothing if the
+ * insertion point isn't editable. The @default_editable parameter
+ * indicates whether the text is editable at @iter if no tags
+ * enclosing @iter affect editability. Typically the result of
+ * gtk_text_view_get_editable() is appropriate here.
+ *
+ * Returns: whether an insertion was possible at @iter
+ **/
 gboolean
 gtk_text_buffer_insert_range_interactive (GtkTextBuffer     *buffer,
                                           GtkTextIter       *iter,
@@ -598,9 +919,13 @@ gtk_text_buffer_insert_range_interactive (GtkTextBuffer     *buffer,
                         buffer->tag_table, FALSE);
 
 
-  /* FIXME */
-
-  return FALSE;
+  if (gtk_text_iter_editable (iter, default_editable))
+    {
+      gtk_text_buffer_real_insert_range (buffer, iter, start, end, TRUE);
+      return TRUE;
+    }
+  else
+    return FALSE;
 }
 
 /**
@@ -981,7 +1306,9 @@ gtk_text_buffer_get_text (GtkTextBuffer      *buffer,
  * embedded images, so byte and character indexes into
  * the returned string <emphasis>do</emphasis> correspond to byte
  * and character indexes into the buffer. Contrast with
- * gtk_text_buffer_get_text ().
+ * gtk_text_buffer_get_text (). Note that 0xFFFD can occur in normal
+ * text as well, so it is not a reliable indicator that a pixbuf or
+ * widget is in the buffer.
  *
  * Return value: an allocated UTF-8 string
  **/
@@ -1707,38 +2034,6 @@ gtk_text_buffer_get_char_count (GtkTextBuffer *buffer)
   return gtk_text_btree_char_count (get_btree (buffer));
 }
 
-GSList*
-gtk_text_buffer_get_tags               (GtkTextBuffer      *buffer,
-                                        const GtkTextIter  *iter)
-{
-  GSList *retval = NULL;
-  GtkTextTag** tags;
-  gint count = 0;
-
-  tags = gtk_text_btree_get_tags (iter, &count);
-
-  if (count > 0)
-    {
-      gint i;
-
-      gtk_text_tag_array_sort (tags, count);
-
-      i = 0;
-      while (i < count)
-        {
-          retval = g_slist_prepend (retval, tags[i]);
-          ++i;
-        }
-
-      retval = g_slist_reverse (retval);
-    }
-
-  if (tags)
-    g_free (tags);
-
-  return retval;
-}
-
 /* Called when we lose the primary selection.
  */
 static void
@@ -1771,95 +2066,176 @@ clipboard_get_cb (GtkClipboard     *clipboard,
                   gpointer          data)
 {
   GtkTextBuffer *buffer = GTK_TEXT_BUFFER (data);
-  gchar *str;
   GtkTextIter start, end;
 
   if (gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
     {
-      /* Extract the selected text */
-      str = gtk_text_iter_get_visible_text (&start, &end);
-      gtk_selection_data_set_text (selection_data, str);
-      g_free (str);
+      if (selection_data->target ==
+          gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE))
+        {
+          /* Provide the address of the buffer; this will only be
+           * used within-process
+           */
+          gtk_selection_data_set (selection_data,
+                                  gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE),
+                                  8, /* bytes */
+                                  (void*)&buffer,
+                                  sizeof (buffer));
+        }
+      else
+        {
+          gchar *str;
+          
+          str = gtk_text_iter_get_visible_text (&start, &end);
+          gtk_selection_data_set_text (selection_data, str);
+          g_free (str);
+        }
     }
 }
 
-/* Called when we request a paste and receive the data
- */
 static void
-clipboard_received (GtkClipboard *clipboard,
-                    const gchar  *str,
-                    gpointer      data)
+get_paste_point (GtkTextBuffer *buffer,
+                 GtkTextIter   *iter,
+                 gboolean       clear_afterward)
 {
-  ClipboardRequest *request_data = data;
-  GtkTextBuffer *buffer = request_data->buffer;
+  GtkTextIter insert_point;
+  GtkTextMark *paste_point_override;
 
-  if (str)
-    {
-      gboolean reselect;
-      GtkTextIter insert_point;
-      GtkTextMark *paste_point_override;
+  paste_point_override = gtk_text_buffer_get_mark (buffer,
+                                                   "gtk_paste_point_override");
 
-      paste_point_override = gtk_text_buffer_get_mark (buffer,
-                                                       "gtk_paste_point_override");
+  if (paste_point_override != NULL)
+    {
+      gtk_text_buffer_get_iter_at_mark (buffer, &insert_point,
+                                        paste_point_override);
+      if (clear_afterward)
+        gtk_text_buffer_delete_mark (buffer,
+                                     gtk_text_buffer_get_mark (buffer,
+                                                               "gtk_paste_point_override"));
+    }
+  else
+    {
+      gtk_text_buffer_get_iter_at_mark (buffer, &insert_point,
+                                        gtk_text_buffer_get_mark (buffer,
+                                                                  "insert"));
+    }
 
-      if (paste_point_override != NULL)
-        {
-          gtk_text_buffer_get_iter_at_mark (buffer, &insert_point,
-                                            paste_point_override);
-          gtk_text_buffer_delete_mark (buffer,
-                                       gtk_text_buffer_get_mark (buffer,
-                                                                 "gtk_paste_point_override"));
-        }
-      else
-        {
-          gtk_text_buffer_get_iter_at_mark (buffer, &insert_point,
-                                            gtk_text_buffer_get_mark (buffer,
-                                                                      "insert"));
-        }
+  *iter = insert_point;
+}
 
-      reselect = FALSE;
+static void
+pre_paste_prep (ClipboardRequest *request_data,
+                GtkTextIter      *insert_point)
+{
+  GtkTextBuffer *buffer = request_data->buffer;
 
-      /* FIXME ALL OF THIS - I think that the "best method" is that when pasting
-       * with the cursor inside the selection area, you replace the selection
-       * with the new text, otherwise, you simply insert the new text at
-       * the point where the click occured, unselecting any selected text.
-       *
-       * This probably is best implemented as a "replace_selection" flag in
-       * ClipboardRequest.
-       */
-#if 0
-      if ((TRUE/* Text is selected FIXME */) &&
-          (!buffer->have_selection || request_data->is_clipboard))
+  if (request_data->replace_selection)
+    {
+      GtkTextIter start, end;
+      
+      if (gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
         {
-          reselect = TRUE;
-
-          if (buffer->have_selection)
-            {
-              /* FIXME Delete currently-selected chars but don't give up X
-                 selection since we'll use the newly-pasted stuff as
-                 a new X selection */
-
-            }
+          if (request_data->interactive)
+            gtk_text_buffer_delete_interactive (buffer,
+                                                &start,
+                                                &end,
+                                                request_data->default_editable);
           else
-            ; /* FIXME Delete selected chars and give up X selection */
+            gtk_text_buffer_delete (buffer, &start, &end);
         }
-#endif
+    }
+      
+  get_paste_point (buffer, insert_point, TRUE);
+}
+
+/* Called when we request a paste and receive the text data
+ */
+static void
+clipboard_text_received (GtkClipboard *clipboard,
+                         const gchar  *str,
+                         gpointer      data)
+{
+  ClipboardRequest *request_data = data;
+  GtkTextBuffer *buffer = request_data->buffer;
 
+  if (str)
+    {
+      GtkTextIter insert_point;
+
+      pre_paste_prep (request_data, &insert_point);
+      
       if (request_data->interactive)
         gtk_text_buffer_insert_interactive (buffer, &insert_point,
                                             str, -1, request_data->default_editable);
       else
         gtk_text_buffer_insert (buffer, &insert_point,
                                 str, -1);
-
-      if (reselect)
-        ; /* FIXME Select the region of text we just inserted */
     }
 
   g_object_unref (G_OBJECT (buffer));
   g_free (request_data);
 }
 
+static void
+clipboard_buffer_received (GtkClipboard     *clipboard,
+                           GtkSelectionData *selection_data,
+                           gpointer          data)
+{
+  ClipboardRequest *request_data = data;
+  GtkTextBuffer *buffer = request_data->buffer;
+  GdkWindow *owner;
+  GtkTextBuffer *src_buffer = NULL;
+  GtkTextIter src_start, src_end;
+  GtkTextIter insert_point;
+  
+  /* If we can get the owner, the selection is in-process */
+  owner = gdk_selection_owner_get (selection_data->selection);
+
+  if (owner == NULL)
+    goto try_another_target;
+  
+  if (selection_data->type != gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE))
+    goto try_another_target;
+
+  if (selection_data->length != sizeof (src_buffer))
+    return;
+          
+  memcpy (&src_buffer, selection_data->data, sizeof (src_buffer));
+          
+  g_return_if_fail (GTK_IS_TEXT_BUFFER (src_buffer));
+
+  if (gtk_text_buffer_get_tag_table (src_buffer) !=
+      gtk_text_buffer_get_tag_table (buffer))
+    goto try_another_target;
+  
+  /* We're about to emit a bunch of signals, so be safe */
+  g_object_ref (G_OBJECT (src_buffer));
+
+  pre_paste_prep (request_data, &insert_point);
+  
+  if (gtk_text_buffer_get_selection_bounds (src_buffer,
+                                            &src_start,
+                                            &src_end))
+    {
+      gtk_text_buffer_real_insert_range (buffer,
+                                         &insert_point,
+                                         &src_start,
+                                         &src_end,
+                                         request_data->interactive);
+    }
+
+  g_object_unref (G_OBJECT (src_buffer));
+
+  return;
+  
+ try_another_target:
+
+  /* Request the text selection instead */
+  gtk_clipboard_request_text (clipboard,
+                              clipboard_text_received,
+                              data);
+}
+
 static void
 gtk_text_buffer_update_primary_selection (GtkTextBuffer *buffer)
 {
@@ -1867,7 +2243,8 @@ gtk_text_buffer_update_primary_selection (GtkTextBuffer *buffer)
     { "STRING", 0, TARGET_STRING },
     { "TEXT",   0, TARGET_TEXT },
     { "COMPOUND_TEXT", 0, TARGET_COMPOUND_TEXT },
-    { "UTF8_STRING", 0, TARGET_UTF8_STRING }
+    { "UTF8_STRING", 0, TARGET_UTF8_STRING },
+    { "GTK_TEXT_BUFFER_CONTENTS", 0, TARGET_TEXT_BUFFER_CONTENTS }
   };
 
   GtkTextIter start;
@@ -1897,25 +2274,42 @@ gtk_text_buffer_update_primary_selection (GtkTextBuffer *buffer)
 
 static void
 paste (GtkTextBuffer *buffer,
-       gboolean is_clipboard,
-       gboolean interactive,
-       gboolean default_editable)
+       gboolean       is_clipboard,
+       gboolean       interactive,
+       gboolean       default_editable)
 {
   ClipboardRequest *data = g_new (ClipboardRequest, 1);
-
+  GtkTextIter paste_point;
+  GtkTextIter start, end;
+  
   data->buffer = buffer;
   g_object_ref (G_OBJECT (buffer));
   data->interactive = interactive;
   data->default_editable = default_editable;
 
-  gtk_clipboard_request_text (gtk_clipboard_get (is_clipboard ? GDK_NONE : GDK_SELECTION_PRIMARY),
-                              clipboard_received, data);
+  /* When pasting with the cursor inside the selection area, you
+   * replace the selection with the new text, otherwise, you
+   * simply insert the new text at the point where the click
+   * occured, unselecting any selected text. The replace_selection
+   * flag toggles this behavior.
+   */
+  data->replace_selection = FALSE;
+  
+  get_paste_point (buffer, &paste_point, FALSE);
+  if (gtk_text_buffer_get_selection_bounds (buffer, &start, &end) &&
+      gtk_text_iter_in_range (&paste_point, &start, &end))
+    data->replace_selection = TRUE;
+  
+  gtk_clipboard_request_contents (gtk_clipboard_get (is_clipboard ? GDK_NONE : GDK_SELECTION_PRIMARY),
+
+                                  gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE),
+                                  clipboard_buffer_received, data);
 }
 
 void
-gtk_text_buffer_paste_primary (GtkTextBuffer *buffer,
-                               GtkTextIter   *override_location,
-                               gboolean       default_editable)
+gtk_text_buffer_paste_primary (GtkTextBuffer       *buffer,
+                               const GtkTextIter   *override_location,
+                               gboolean             default_editable)
 {
   if (override_location != NULL)
     gtk_text_buffer_create_mark (buffer,
@@ -1962,11 +2356,12 @@ cut_or_copy (GtkTextBuffer *buffer,
              gboolean default_editable)
 {
   /* We prefer to cut the selected region between selection_bound and
-     insertion point. If that region is empty, then we cut the region
-     between the "anchor" and the insertion point (this is for C-space
-     and M-w and other Emacs-style copy/yank keys). Note that insert
-     and selection_bound are guaranteed to exist, but the anchor only
-     exists sometimes. */
+   * insertion point. If that region is empty, then we cut the region
+   * between the "anchor" and the insertion point (this is for
+   * C-space and M-w and other Emacs-style copy/yank keys). Note that
+   * insert and selection_bound are guaranteed to exist, but the
+   * anchor only exists sometimes.
+   */
   GtkTextIter start;
   GtkTextIter end;
 
index c1b5fcdd58ed87b9529bd4da382b0de5c67ba465..54844e14653c9826acd6fe9c24724859209926e9 100644 (file)
@@ -283,10 +283,6 @@ void gtk_text_buffer_get_iter_at_child_anchor (GtkTextBuffer      *buffer,
 /* There's no get_first_iter because you just get the iter for
    line or char 0 */
 
-GSList         *gtk_text_buffer_get_tags (GtkTextBuffer     *buffer,
-                                          const GtkTextIter *iter);
-
-
 /* Used to keep track of whether the buffer needs saving; anytime the
    buffer contents change, the modified flag is turned on. Whenever
    you save, turn it off. Tags and marks do not affect the modified
@@ -297,9 +293,9 @@ gboolean        gtk_text_buffer_modified                (GtkTextBuffer *buffer);
 void            gtk_text_buffer_set_modified            (GtkTextBuffer *buffer,
                                                          gboolean       setting);
 
-void            gtk_text_buffer_paste_primary           (GtkTextBuffer *buffer,
-                                                         GtkTextIter   *override_location,
-                                                         gboolean       default_editable);
+void            gtk_text_buffer_paste_primary           (GtkTextBuffer       *buffer,
+                                                         const GtkTextIter   *override_location,
+                                                         gboolean             default_editable);
 void            gtk_text_buffer_cut_clipboard           (GtkTextBuffer *buffer,
                                                          gboolean       default_editable);
 void            gtk_text_buffer_copy_clipboard          (GtkTextBuffer *buffer);
index e57855551af987671786a97a54069fdd8c9bc861..f7713d30992a6ea6c021e38156d4d94ac0a7e6af 100644 (file)
@@ -580,11 +580,14 @@ gtk_text_iter_get_offset (const GtkTextIter *iter)
   if (real == NULL)
     return 0;
 
+  check_invariants (iter);
+  
   if (real->cached_char_index < 0)
     {
+      ensure_char_offsets (real);
+      
       real->cached_char_index =
         gtk_text_line_char_index (real->line);
-      ensure_char_offsets (real);
       real->cached_char_index += real->line_char_offset;
     }
 
@@ -722,7 +725,7 @@ gtk_text_iter_get_char (const GtkTextIter *iter)
   else if (real->segment->type == &gtk_text_char_type)
     {
       ensure_byte_offsets (real);
-
+      
       return g_utf8_get_char (real->segment->body.chars +
                               real->segment_byte_offset);
     }
@@ -743,7 +746,9 @@ gtk_text_iter_get_char (const GtkTextIter *iter)
  * character 0xFFFD for iterable non-character elements in the buffer,
  * such as images.  Because images are encoded in the slice, byte and
  * character offsets in the returned array will correspond to byte
- * offsets in the text buffer.
+ * offsets in the text buffer. Note that 0xFFFD can occur in normal
+ * text as well, so it is not a reliable indicator that a pixbuf or
+ * widget is in the buffer.
  *
  * Return value: slice of text from the buffer
  **/
@@ -1169,6 +1174,56 @@ gtk_text_iter_has_tag           (const GtkTextIter   *iter,
     }
 }
 
+/**
+ * gtk_text_iter_get_tags:
+ * @iter: a #GtkTextIter
+ * 
+ * Returns a list of tags that apply to @iter, in ascending order of
+ * priority (highest-priority tags are last). The #GtkTextTag in the
+ * list don't have a reference added, but you have to free the list
+ * itself.
+ * 
+ * Return value: list of #GtkTextTag
+ **/
+GSList*
+gtk_text_iter_get_tags (const GtkTextIter *iter)
+{
+  GtkTextTag** tags;
+  gint tag_count = 0;
+  gint i;
+  GSList *retval;
+  
+  g_return_val_if_fail (iter != NULL, NULL);
+  
+  /* Get the tags at this spot */
+  tags = gtk_text_btree_get_tags (iter, &tag_count);
+
+  /* No tags, use default style */
+  if (tags == NULL || tag_count == 0)
+    {
+      if (tags)
+        g_free (tags);
+
+      return NULL;
+    }
+
+  /* Sort tags in ascending order of priority */
+  gtk_text_tag_array_sort (tags, tag_count);
+
+  retval = NULL;
+  i = 0;
+  while (i < tag_count)
+    {
+      retval = g_slist_prepend (retval, tags[i]);
+      ++i;
+    }
+  
+  g_free (tags);
+
+  /* Return tags in ascending order of priority */
+  return g_slist_reverse (retval);
+}
+
 /**
  * gtk_text_iter_editable:
  * @iter: an iterator
@@ -2654,7 +2709,9 @@ gtk_text_iter_forward_to_newline (GtkTextIter *iter)
  * #GtkTextTag @tag, or to the next toggle of any tag if
  * @tag is NULL. If no matching tag toggles are found,
  * returns FALSE, otherwise TRUE. Does not return toggles
- * located at @iter, only toggles after @iter.
+ * located at @iter, only toggles after @iter. Sets @iter to
+ * the location of the toggle, or to the end of the buffer
+ * if no toggle is found.
  *
  * Return value: whether we found a tag toggle after @iter
  **/
@@ -2734,7 +2791,9 @@ gtk_text_iter_forward_to_tag_toggle (GtkTextIter *iter,
  * #GtkTextTag @tag, or to the next toggle of any tag if
  * @tag is NULL. If no matching tag toggles are found,
  * returns FALSE, otherwise TRUE. Does not return toggles
- * located at @iter, only toggles before @iter.
+ * located at @iter, only toggles before @iter. Sets @iter
+ * to the location of the toggle, or the start of the buffer
+ * if no toggle is found.
  *
  * Return value: whether we found a tag toggle before @iter
  **/
@@ -2836,16 +2895,37 @@ matches_pred (GtkTextIter *iter,
   return (*pred) (ch, user_data);
 }
 
+/**
+ * gtk_text_iter_forward_find_char:
+ * @iter: a #GtkTextIter
+ * @pred: a function to be called on each character
+ * @user_data: user data for @pred
+ * @limit: search limit, or %NULL for none 
+ * 
+ * Advances @iter, calling @pred on each character. If
+ * @pred returns %TRUE, returns %TRUE and stops scanning.
+ * If @pred never returns %TRUE, @iter is set to @limit if
+ * @limit is non-%NULL, otherwise to the end iterator.
+ * 
+ * Return value: whether a match was found
+ **/
 gboolean
-gtk_text_iter_forward_find_char (GtkTextIter *iter,
+gtk_text_iter_forward_find_char (GtkTextIter         *iter,
                                  GtkTextCharPredicate pred,
-                                 gpointer user_data)
+                                 gpointer             user_data,
+                                 const GtkTextIter   *limit)
 {
   g_return_val_if_fail (iter != NULL, FALSE);
   g_return_val_if_fail (pred != NULL, FALSE);
 
-  while (gtk_text_iter_next_char (iter))
-    {
+  if (limit &&
+      gtk_text_iter_compare (iter, limit) >= 0)
+    return FALSE;
+  
+  while ((limit == NULL ||
+          !gtk_text_iter_equal (limit, iter)) &&
+         gtk_text_iter_next_char (iter))
+    {      
       if (matches_pred (iter, pred, user_data))
         return TRUE;
     }
@@ -2854,14 +2934,21 @@ gtk_text_iter_forward_find_char (GtkTextIter *iter,
 }
 
 gboolean
-gtk_text_iter_backward_find_char (GtkTextIter *iter,
+gtk_text_iter_backward_find_char (GtkTextIter         *iter,
                                   GtkTextCharPredicate pred,
-                                  gpointer user_data)
+                                  gpointer             user_data,
+                                  const GtkTextIter   *limit)
 {
   g_return_val_if_fail (iter != NULL, FALSE);
   g_return_val_if_fail (pred != NULL, FALSE);
 
-  while (gtk_text_iter_prev_char (iter))
+  if (limit &&
+      gtk_text_iter_compare (iter, limit) <= 0)
+    return FALSE;
+  
+  while ((limit == NULL ||
+          !gtk_text_iter_equal (limit, iter)) &&
+         gtk_text_iter_prev_char (iter))
     {
       if (matches_pred (iter, pred, user_data))
         return TRUE;
@@ -3060,13 +3147,28 @@ strbreakup (const char *string,
   return str_array;
 }
 
+/**
+ * gtk_text_iter_forward_search:
+ * @iter: start of search
+ * @str: a search string
+ * @visible_only: if %TRUE, search only visible text
+ * @slice: if %TRUE, @str contains 0xFFFD when we want to match widgets, pixbufs
+ * @match_start: return location for start of match, or %NULL
+ * @match_end: return location for end of match, or %NULL
+ * @limit: bound for the search, or %NULL for the end of the buffer
+ * 
+ * 
+ * 
+ * Return value: whether a match was found
+ **/
 gboolean
 gtk_text_iter_forward_search (const GtkTextIter *iter,
                               const gchar       *str,
                               gboolean           visible_only,
                               gboolean           slice,
                               GtkTextIter       *match_start,
-                              GtkTextIter       *match_end)
+                              GtkTextIter       *match_end,
+                              const GtkTextIter *limit)
 {
   gchar **lines = NULL;
   GtkTextIter match;
@@ -3076,12 +3178,21 @@ gtk_text_iter_forward_search (const GtkTextIter *iter,
   g_return_val_if_fail (iter != NULL, FALSE);
   g_return_val_if_fail (str != NULL, FALSE);
 
+  if (limit &&
+      gtk_text_iter_compare (iter, limit) >= 0)
+    return FALSE;
+  
   if (*str == '\0')
     {
       /* If we can move one char, return the empty string there */
       match = *iter;
+      
       if (gtk_text_iter_next_char (&match))
         {
+          if (limit &&
+              gtk_text_iter_equal (&match, limit))
+            return FALSE;
+          
           if (match_start)
             *match_start = match;
           if (match_end)
@@ -3106,17 +3217,26 @@ gtk_text_iter_forward_search (const GtkTextIter *iter,
        */
       GtkTextIter end;
 
+      if (limit &&
+          gtk_text_iter_compare (&search, limit) >= 0)
+        break;
+      
       if (lines_match (&search, (const gchar**)lines,
                        visible_only, slice, &match, &end))
         {
-          retval = TRUE;
-
-          if (match_start)
-            *match_start = match;
-
-          if (match_end)
-            *match_end = end;
-
+          if (limit == NULL ||
+              (limit &&
+               gtk_text_iter_compare (&end, limit) < 0))
+            {
+              retval = TRUE;
+              
+              if (match_start)
+                *match_start = match;
+              
+              if (match_end)
+                *match_end = end;
+            }
+          
           break;
         }
     }
@@ -3345,13 +3465,28 @@ my_strrstr (const gchar *haystack,
   return NULL;
 }
 
+/**
+ * gtk_text_iter_backward_search:
+ * @iter: a #GtkTextIter where the search begins
+ * @str: search string
+ * @visible_only: if %TRUE search only visible text
+ * @slice: if %TRUE the search string contains 0xFFFD to match pixbufs, widgets
+ * @match_start: return location for start of match, or %NULL
+ * @match_end: return location for end of match, or %NULL
+ * @limit: location of last possible @match_start, or %NULL for start of buffer
+ * 
+ * 
+ * 
+ * Return value: whether a match was found
+ **/
 gboolean
 gtk_text_iter_backward_search (const GtkTextIter *iter,
                                const gchar       *str,
                                gboolean           visible_only,
                                gboolean           slice,
                                GtkTextIter       *match_start,
-                               GtkTextIter       *match_end)
+                               GtkTextIter       *match_end,
+                               const GtkTextIter *limit)
 {
   gchar **lines = NULL;
   gchar **l;
@@ -3362,11 +3497,18 @@ gtk_text_iter_backward_search (const GtkTextIter *iter,
   g_return_val_if_fail (iter != NULL, FALSE);
   g_return_val_if_fail (str != NULL, FALSE);
 
+  if (limit &&
+      gtk_text_iter_compare (limit, iter) > 0)
+    return FALSE;
+  
   if (*str == '\0')
     {
       /* If we can move one char, return the empty string there */
       GtkTextIter match = *iter;
 
+      if (limit && gtk_text_iter_equal (limit, &match))
+        return FALSE;
+      
       if (gtk_text_iter_prev_char (&match))
         {
           if (match_start)
@@ -3404,6 +3546,13 @@ gtk_text_iter_backward_search (const GtkTextIter *iter,
     {
       gchar *first_line_match;
 
+      if (limit &&
+          gtk_text_iter_compare (limit, &win.first_line_end) > 0)
+        {
+          /* We're now before the search limit, abort. */
+          goto out;
+        }
+      
       /* If there are multiple lines, the first line will
        * end in '\n', so this will only match at the
        * end of the first line, which is correct.
@@ -3416,17 +3565,22 @@ gtk_text_iter_backward_search (const GtkTextIter *iter,
           /* Match! */
           gint offset;
           GtkTextIter next;
-
+          GtkTextIter start_tmp;
+          
           /* Offset to start of search string */
           offset = g_utf8_strlen (*win.lines, first_line_match - *win.lines);
 
           next = win.first_line_start;
+          start_tmp = next;
+          forward_chars_with_skipping (&start_tmp, offset,
+                                       visible_only, !slice);
+
+          if (limit &&
+              gtk_text_iter_compare (limit, &start_tmp) > 0)
+            goto out; /* match was bogus */
+          
           if (match_start)
-            {
-              *match_start = next;
-              forward_chars_with_skipping (match_start, offset,
-                                           visible_only, !slice);
-            }
+            *match_start = start_tmp;
 
           /* Go to end of search string */
           l = lines;
@@ -3451,7 +3605,7 @@ gtk_text_iter_backward_search (const GtkTextIter *iter,
  out:
   lines_window_free (&win);
   g_strfreev (lines);
-
+  
   return retval;
 }
 
@@ -3655,7 +3809,7 @@ void
 gtk_text_btree_get_iter_at_line      (GtkTextBTree   *tree,
                                       GtkTextIter    *iter,
                                       GtkTextLine    *line,
-                                      gint             byte_offset)
+                                      gint            byte_offset)
 {
   g_return_if_fail (iter != NULL);
   g_return_if_fail (tree != NULL);
@@ -3822,13 +3976,13 @@ gtk_text_iter_check (const GtkTextIter *iter)
 {
   const GtkTextRealIter *real = (const GtkTextRealIter*)iter;
   gint line_char_offset, line_byte_offset, seg_char_offset, seg_byte_offset;
-  GtkTextLineSegment *byte_segment;
-  GtkTextLineSegment *byte_any_segment;
-  GtkTextLineSegment *char_segment;
-  GtkTextLineSegment *char_any_segment;
+  GtkTextLineSegment *byte_segment = NULL;
+  GtkTextLineSegment *byte_any_segment = NULL;
+  GtkTextLineSegment *char_segment = NULL;
+  GtkTextLineSegment *char_any_segment = NULL;
   gboolean segments_updated;
 
-  /* We are going to check our class invariants for the Iter class. */
+  /* This function checks our class invariants for the Iter class. */
 
   g_assert (sizeof (GtkTextIter) == sizeof (GtkTextRealIter));
 
@@ -3891,6 +4045,15 @@ gtk_text_iter_check (const GtkTextIter *iter)
 
           if (seg_byte_offset != real->segment_byte_offset)
             g_error ("wrong segment byte offset was stored in iterator");
+
+          if (byte_segment->type == &gtk_text_char_type)
+            {
+              const gchar *p;
+              p = byte_segment->body.chars + seg_byte_offset;
+              
+              if (!gtk_text_byte_begins_utf8_char (p))
+                g_error ("broken iterator byte index pointed into the middle of a character");
+            }
         }
     }
 
@@ -3904,7 +4067,7 @@ gtk_text_iter_check (const GtkTextIter *iter)
         g_error ("wrong char offset was stored in iterator");
 
       if (segments_updated)
-        {
+        {          
           if (real->segment != char_segment)
             g_error ("wrong segment was stored in iterator");
 
@@ -3913,6 +4076,17 @@ gtk_text_iter_check (const GtkTextIter *iter)
 
           if (seg_char_offset != real->segment_char_offset)
             g_error ("wrong segment char offset was stored in iterator");
+
+          if (char_segment->type == &gtk_text_char_type)
+            {
+              const gchar *p;
+              p = g_utf8_offset_to_pointer (char_segment->body.chars,
+                                            seg_char_offset);
+
+              /* hmm, not likely to happen eh */
+              if (!gtk_text_byte_begins_utf8_char (p))
+                g_error ("broken iterator char offset pointed into the middle of a character");
+            }
         }
     }
 
@@ -3945,6 +4119,9 @@ gtk_text_iter_check (const GtkTextIter *iter)
 
           if (char_offset != seg_char_offset)
             g_error ("char offset did not correspond to byte offset");
+
+          if (!gtk_text_byte_begins_utf8_char (char_segment->body.chars + seg_byte_offset))
+            g_error ("byte index for iterator does not index the start of a character");
         }
     }
 
index 3e649d0b40b34c36e3c88cb06d2f4321d6ae5e68..caadecb2a272c920284845ba864a1ef157cfdc76 100644 (file)
@@ -119,6 +119,7 @@ gboolean gtk_text_iter_toggles_tag       (const GtkTextIter  *iter,
 
 gboolean gtk_text_iter_has_tag           (const GtkTextIter   *iter,
                                           GtkTextTag          *tag);
+GSList  *gtk_text_iter_get_tags          (const GtkTextIter   *iter);
 
 gboolean gtk_text_iter_editable          (const GtkTextIter   *iter,
                                           gboolean             default_setting);
@@ -170,8 +171,9 @@ gboolean gtk_text_iter_forward_to_newline (GtkTextIter *iter);
 
 
 /* returns TRUE if a toggle was found; NULL for the tag pointer
-   means "any tag toggle", otherwise the next toggle of the
-   specified tag is located. */
+ * means "any tag toggle", otherwise the next toggle of the
+ * specified tag is located.
+ */
 gboolean gtk_text_iter_forward_to_tag_toggle (GtkTextIter *iter,
                                               GtkTextTag  *tag);
 
@@ -180,27 +182,30 @@ gboolean gtk_text_iter_backward_to_tag_toggle (GtkTextIter *iter,
 
 typedef gboolean (* GtkTextCharPredicate) (gunichar ch, gpointer user_data);
 
-gboolean gtk_text_iter_forward_find_char      (GtkTextIter *iter,
-                                               GtkTextCharPredicate pred,
-                                               gpointer user_data);
-
-gboolean gtk_text_iter_backward_find_char     (GtkTextIter *iter,
-                                               GtkTextCharPredicate pred,
-                                               gpointer user_data);
+gboolean gtk_text_iter_forward_find_char  (GtkTextIter          *iter,
+                                           GtkTextCharPredicate  pred,
+                                           gpointer              user_data,
+                                           const GtkTextIter    *limit);
+gboolean gtk_text_iter_backward_find_char (GtkTextIter          *iter,
+                                           GtkTextCharPredicate  pred,
+                                           gpointer              user_data,
+                                           const GtkTextIter    *limit);
 
 gboolean gtk_text_iter_forward_search  (const GtkTextIter *iter,
                                         const gchar       *str,
                                         gboolean           visible_only,
                                         gboolean           slice,
                                         GtkTextIter       *match_start,
-                                        GtkTextIter       *match_end);
+                                        GtkTextIter       *match_end,
+                                        const GtkTextIter *limit);
+
 gboolean gtk_text_iter_backward_search (const GtkTextIter *iter,
                                         const gchar       *str,
                                         gboolean           visible_only,
                                         gboolean           slice,
                                         GtkTextIter       *match_start,
-                                        GtkTextIter       *match_end);
-
+                                        GtkTextIter       *match_end,
+                                        const GtkTextIter *limit);
 
 
 /*
index cba5557b31a9516ec32d4b91c1bbb9b834dd20eb..9f84c001ef95e516e56e8625f8f3e86d21d27cc4 100644 (file)
@@ -2235,7 +2235,7 @@ gtk_text_layout_move_iter_to_line_end (GtkTextLayout *layout,
         {
           gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer),
                                            iter, line,
-                                           direction < 0 ? byte_offset : layout_line->length);
+                                           direction < 0 ? byte_offset : byte_offset + layout_line->length);
 
           /* FIXME: Move back one position to avoid going to next line
            */
index 13587007bc2ab064b6f475c395b3ca65377f7a0b..4e20eb300c6a4898f26fd60ad352a502155c6cd5 100644 (file)
@@ -128,7 +128,7 @@ gtk_text_mark_finalize (GObject *obj)
 }
 
 /**
- * gtk_text_mark_is_visible:
+ * gtk_text_mark_get_visible:
  * @mark: a #GtkTextMark
  * 
  * Returns %TRUE if the mark is visible (i.e. a cursor is displayed
@@ -137,7 +137,7 @@ gtk_text_mark_finalize (GObject *obj)
  * Return value: %TRUE if visible
  **/
 gboolean
-gtk_text_mark_is_visible (GtkTextMark *mark)
+gtk_text_mark_get_visible (GtkTextMark *mark)
 {
   GtkTextLineSegment *seg;
 
index cdcaeab4bceed9b9a7b7d75ed029a37e0a54cfdc..e2130c5acdd0cdcf5caed00d352138dfefda1f78 100644 (file)
@@ -83,7 +83,7 @@ GType        gtk_text_mark_get_type   (void) G_GNUC_CONST;
 
 void         gtk_text_mark_set_visible (GtkTextMark *mark,
                                         gboolean     setting);
-gboolean     gtk_text_mark_is_visible  (GtkTextMark *mark);
+gboolean     gtk_text_mark_get_visible (GtkTextMark *mark);
 /* FIXME gconst */
 const char  *gtk_text_mark_get_name    (GtkTextMark *mark);
 gboolean     gtk_text_mark_get_deleted (GtkTextMark *mark);
index 66f0a672b94d80e35d23d969100b3d0f12a6d500..33d10833174f21e6464831e5e267befc300720b5 100644 (file)
@@ -102,6 +102,9 @@ gtk_text_line_segment_split (const GtkTextIter *iter)
 
   count = gtk_text_iter_get_line_index (iter);
 
+  if (gtk_debug_flags & GTK_DEBUG_TEXT)
+    gtk_text_iter_check (iter);
+  
   prev = NULL;
   seg = line->segments;
 
index bc054fb17391cf8cfe31e4f31da1f021ed327ed9..1dedcaf068b57b895c7dbbe4db1a705b136021dd 100644 (file)
@@ -2040,14 +2040,14 @@ emit_event_on_tags (GtkWidget   *widget,
 
   text_view = GTK_TEXT_VIEW (widget);
 
-  tags = gtk_text_buffer_get_tags (get_buffer (text_view), iter);
+  tags = gtk_text_iter_get_tags (iter);
 
   tmp = tags;
   while (tmp != NULL)
     {
       GtkTextTag *tag = tmp->data;
 
-      if (gtk_text_tag_event (tag, GTK_OBJECT (widget), event, iter))
+      if (gtk_text_tag_event (tag, G_OBJECT (widget), event, iter))
         {
           retval = TRUE;
           break;
@@ -2818,10 +2818,10 @@ find_whitepace_region (const GtkTextIter *center,
   *start = *center;
   *end = *center;
 
-  if (gtk_text_iter_backward_find_char (start, not_whitespace, NULL))
+  if (gtk_text_iter_backward_find_char (start, not_whitespace, NULL, NULL))
     gtk_text_iter_next_char (start); /* we want the first whitespace... */
   if (whitespace (gtk_text_iter_get_char (end), NULL))
-    gtk_text_iter_forward_find_char (end, not_whitespace, NULL);
+    gtk_text_iter_forward_find_char (end, not_whitespace, NULL, NULL);
 
   return !gtk_text_iter_equal (start, end);
 }
index b55a2a1b9967c56bbfbb74ebd2051945ab41a514..e89c3857ec1e1504768f0c2bd8e66db29ee06ed9 100644 (file)
@@ -141,25 +141,6 @@ struct _GtkRequisition
   gint height;
 };
 
-/* The contents of a selection are returned in a GtkSelectionData
-   structure. selection/target identify the request. 
-   type specifies the type of the return; if length < 0, and
-   the data should be ignored. This structure has object semantics -
-   no fields should be modified directly, they should not be created
-   directly, and pointers to them should not be stored beyond the duration of
-   a callback. (If the last is changed, we'll need to add reference
-   counting.) The time field gives the timestamp at which the data was sent. */
-
-struct _GtkSelectionData
-{
-  GdkAtom selection;
-  GdkAtom target;
-  GdkAtom type;
-  gint   format;
-  guchar *data;
-  gint   length;
-};
-
 /* The widget is the base of the tree for displayable objects.
  *  (A displayable object is one which takes up some amount
  *  of screen real estate). It provides a common base and interface
index d62545f7ae7d93148f9a58a45d87c3aec76973d1..12cfcd0899745bc68457979af2c61b46429ee703 100644 (file)
@@ -1351,7 +1351,8 @@ buffer_search (Buffer     *buffer,
       if (forward)
         {
           while (gtk_text_iter_forward_search (&iter, str, TRUE, FALSE,
-                                               &match_start, &match_end))
+                                               &match_start, &match_end,
+                                               NULL))
             {
               ++i;
               gtk_text_buffer_apply_tag (buffer->buffer, buffer->found_text_tag,
@@ -1363,7 +1364,8 @@ buffer_search (Buffer     *buffer,
       else
         {
           while (gtk_text_iter_backward_search (&iter, str, TRUE, FALSE,
-                                                &match_start, &match_end))
+                                                &match_start, &match_end,
+                                                NULL))
             {
               ++i;
               gtk_text_buffer_apply_tag (buffer->buffer, buffer->found_text_tag,
index d62545f7ae7d93148f9a58a45d87c3aec76973d1..12cfcd0899745bc68457979af2c61b46429ee703 100644 (file)
@@ -1351,7 +1351,8 @@ buffer_search (Buffer     *buffer,
       if (forward)
         {
           while (gtk_text_iter_forward_search (&iter, str, TRUE, FALSE,
-                                               &match_start, &match_end))
+                                               &match_start, &match_end,
+                                               NULL))
             {
               ++i;
               gtk_text_buffer_apply_tag (buffer->buffer, buffer->found_text_tag,
@@ -1363,7 +1364,8 @@ buffer_search (Buffer     *buffer,
       else
         {
           while (gtk_text_iter_backward_search (&iter, str, TRUE, FALSE,
-                                                &match_start, &match_end))
+                                                &match_start, &match_end,
+                                                NULL))
             {
               ++i;
               gtk_text_buffer_apply_tag (buffer->buffer, buffer->found_text_tag,